﻿namespace UFIDA.U9.Cust.HWProject.CreateAPBillHead.CreateAPBilBP
{
    using Newtonsoft.Json;
    using ServiceStack.Redis;
    using System;
	using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Text;
    using System.Text.Json.Serialization;
    using System.Web.Script.Serialization;
    using System.Xml;
    using UFIDA.U9.AP.APApply.Exceptions;
    using UFIDA.U9.Base;
    using UFIDA.U9.Base.UserRole;
    using UFIDA.U9.CBO.FI.DTOs;
    using UFIDA.U9.CBO.SCM.Customer;
    using UFIDA.U9.Cust.HWProject.CreateAPBillHead.APBil;
    using UFIDA.UBF.SystemManage;
    using UFIDA.UBF.SystemManage.Agent;
    using UFSoft.UBF.AopFrame;
    using UFSoft.UBF.Business;
    using UFSoft.UBF.DistributedCache;
    using UFSoft.UBF.PL;
    using UFSoft.UBF.PL.Engine.Cache;
    using UFSoft.UBF.Service;
    using UFSoft.UBF.Transactions;
    using UFSoft.UBF.Util.Context;
    using UFSoft.UBF.Util.DataAccess;
    using static UFIDA.U9.Cust.HWProject.CreateAPBillHead.CreateAPBilBP.CreateAPBilImpementStrategy;

    /// <summary>
    /// CreateAPBil partial 
    /// </summary>	
	public partial class CreateAPBil 
	{	
		internal BaseStrategy Select()
		{
			return new CreateAPBilImpementStrategy();	
		}		
	}
	
	#region  implement strategy	
	/// <summary>
	/// Impement Implement
	/// 
	/// </summary>	
	internal partial class CreateAPBilImpementStrategy : BaseStrategy
	{
		public CreateAPBilImpementStrategy() { }

        public override object Do(object obj)
        {
            CreateAPBil bpObj = (CreateAPBil)obj;
            string resulet = "500";
            //1.判定这条数据是否已经存
            //定时调度BP 创建应付单。然后再推送数据
            #region 批量立应付SV
            //为空代表全部推送
            APBil.APbilHead.EntityList aPbilHeads = new APbilHead.EntityList();
            if (bpObj.SrcSystemType!=null && bpObj.SrcSystemType.Count > 0)
            {
                string srcSystemTypes = string.Join(",", bpObj.SrcSystemType.Select(str => $"'{str}'"));
                aPbilHeads = APBil.APbilHead.Finder.FindAll(string.Format("IsSuccess!='true' and SrcSystemType in ({0}) and Org='{1}'",srcSystemTypes,Context.LoginOrg.Code));
            }
            else
            {
                aPbilHeads = APBil.APbilHead.Finder.FindAll("IsSuccess='false' and OrderStatus='0' and Org='" + Context.LoginOrg.Code + "'");
            }
            if (aPbilHeads == null || aPbilHeads.Count == 0)
            {
                throw new Exception("没有未推送的数据");
            }
            UFIDA.U9.AP.ForAPI.Proxy.APAccrueAPISVProxy proxy = new AP.ForAPI.Proxy.APAccrueAPISVProxy();
            proxy.AccrueAPIDTO = new CBO.FI.DTOs.AccrueAPIDTOData();
            AccrueAPIDTOData apiDto = new AccrueAPIDTOData();
            foreach (APbilHead item in aPbilHeads)
            {
                /*   Redis 
// 初始化 Redis 连接
//ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6378,password=123456");
//IDatabase db = redis.GetDatabase(); 
//// 尝试从 Redis 获取缓存
//string cacheKey = $"WorkOrder:{request.Code}";
//var cachedResult = db.StringGet(cacheKey);

//if (cachedResult.HasValue)
//{
//    // 直接返回缓存结果
//    return JsonConvert.DeserializeObject<ApiResult<List<WorkOrderResponseDTO>>>(cachedResult);
//}
*/
                //先将单号存入Redis中。避免重复操作数据
                MainControl mc = SiteInfo.GetMainControlNew();
                List<UBF.SystemManage.IServer> redisServers = mc.GetServerList(PublicConst.RedisServer);
                if (redisServers == null || redisServers.Count == 0)
                {
                    throw new ArgumentException("系统管理中没正确配置Redis服务器，请先增加Redis服务器，并正确配置机器名与端口!");
                }

                //ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost:6378,password=123456");
                //IDatabase db = redis.GetDatabase();
                //db.StringGet();
                //IDatabase db = redis.GetDatabase();

                //RedisCache cache = new RedisCache(0);


                string m_redisserver = redisServers[0].Position;
                int m_redisport = int.Parse(redisServers[0].ServerProperties[0].Value);
                RedisClient cache = new RedisClient(m_redisserver, m_redisport, redisServers[0].Password, 0);
                //设置过期时间20分钟
                TimeSpan expireInterval = TimeSpan.FromMinutes(20);
                //先查询缓存是否存在
                string key =item.SrcSystemType;
                if (cache.Get<string>(key) == null)
                {
                    // cache.Set(item.SrcSystemType, "1", 6000);
                    cache.Set(item.SrcSystemType, "1", expireInterval);
                    using (UBFTransactionScope scope = new UBFTransactionScope(TransactionOption.RequiresNew))
                    {
                        try
                        {
                            #region 创建应付单
                            if (!string.IsNullOrEmpty(item.AccrueDate))
                            {
                                apiDto.AccrueDate = DateTime.Parse(item.AccrueDate);
                            }
                            else
                            {
                                apiDto.AccrueDate = DateTime.Now;
                            }


                            foreach (APbilLine apbillLine in item.APbilLine)
                            {
                                AccrueDetailAPIDTOData accDetail = new AccrueDetailAPIDTOData();
                                UFIDA.U9.PM.Rcv.RcvLine rcvline = UFIDA.U9.PM.Rcv.RcvLine.Finder.Find("Receivement.DocNo='" + apbillLine.SrcDocNo + "' and  DocLineNo = '" + apbillLine.SrcDocLineNo + "'  and  Receivement.Org=" + Context.LoginOrg.ID + "  ");
                                if (rcvline == null)
                                {
                                    throw new Exception(string.Concat(new object[] { "在编码为:", Context.LoginOrg.Code, "的组织中,未找到单号为:", apbillLine.SrcDocNo, "、行号:", apbillLine.SrcDocLineNo, "的采购收货单。" }));
                                }

                                accDetail.Amount = decimal.Parse(apbillLine.Qty);
                                accDetail.IsRMA = false;
                                accDetail.LineID = rcvline.ID;
                                if (rcvline.TaxSchedule != null)
                                {
                                    if (!string.IsNullOrEmpty(apbillLine.TaxSchedule))
                                    {
                                        CBO.FI.Tax.TaxSchedule taxSch = CBO.FI.Tax.TaxSchedule.Finder.Find("Code=@Code", new OqlParam[] { new OqlParam(apbillLine.TaxSchedule) });
                                        if (taxSch == null)
                                        {
                                            throw new Exception("未找到编号:" + apbillLine.TaxSchedule + ",的税组合!");
                                        }
                                        accDetail.TaxScedule = taxSch.ID;
                                        decimal Qty = decimal.Parse(apbillLine.Qty);
                                        decimal TaxPrice = decimal.Parse(apbillLine.Price);//含税单价
                                        decimal NoTaxPrice = Math.Round(TaxPrice / (1 + taxSch.TaxScheduleTaxs[0].Tax.TaxRate), 2);//未税单价
                                        decimal TaxMoney = Math.Round(Qty * TaxPrice / (1 + taxSch.TaxScheduleTaxs[0].Tax.TaxRate) * taxSch.TaxScheduleTaxs[0].Tax.TaxRate, 2);//税额
                                        decimal NoTaxMoney = Math.Round(Qty * TaxPrice / (1 + taxSch.TaxScheduleTaxs[0].Tax.TaxRate), 2);//未税金额
                                        accDetail.TaxPrice = decimal.Parse(apbillLine.Price);//含税单价
                                        accDetail.NoTaxPrice = NoTaxPrice;//未税单价
                                        accDetail.TaxMoney = TaxMoney;//税额
                                        accDetail.NoTaxMoney = NoTaxMoney;//未税金额
                                        accDetail.TotalMoney = Qty * TaxPrice;//总金额
                                    }
                                    else
                                    {
                                        accDetail.TaxScedule = rcvline.TaxSchedule.Key.ID;
                                        decimal Qty = decimal.Parse(apbillLine.Qty);
                                        decimal TaxPrice = decimal.Parse(apbillLine.Price);//含税单价
                                        decimal NoTaxPrice = Math.Round(TaxPrice / (1 + rcvline.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate), 2);//未税单价
                                        decimal TaxMoney = Math.Round(Qty * TaxPrice / (1 + rcvline.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate) * rcvline.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate, 2);//税额
                                        decimal NoTaxMoney = Math.Round(Qty * TaxPrice / (1 + rcvline.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate), 2);//未税金额
                                        accDetail.TaxPrice = decimal.Parse(apbillLine.Price);//含税单价
                                        accDetail.NoTaxPrice = NoTaxPrice;//未税单价
                                        accDetail.TaxMoney = TaxMoney;//税额
                                        accDetail.NoTaxMoney = NoTaxMoney;//未税金额
                                        accDetail.TotalMoney = Qty * TaxPrice;//总金额
                                    }
                                }
                                else
                                {
                                    if (!string.IsNullOrEmpty(apbillLine.TaxSchedule))
                                    {
                                        CBO.FI.Tax.TaxSchedule taxSch = CBO.FI.Tax.TaxSchedule.Finder.Find("Code=@Code", new OqlParam[] { new OqlParam(apbillLine.TaxSchedule) });
                                        if (taxSch == null)
                                        {
                                            throw new Exception("未找到编号:" + apbillLine.TaxSchedule + ",的税组合!");
                                        }
                                        accDetail.TaxScedule = taxSch.ID;
                                        decimal Qty = decimal.Parse(apbillLine.Qty);
                                        decimal TaxPrice = decimal.Parse(apbillLine.Price);//含税单价
                                        decimal NoTaxPrice = Math.Round(TaxPrice / (1 + taxSch.TaxScheduleTaxs[0].Tax.TaxRate), 2);//未税单价
                                        decimal TaxMoney = Math.Round(Qty * TaxPrice / (1 + taxSch.TaxScheduleTaxs[0].Tax.TaxRate) * taxSch.TaxScheduleTaxs[0].Tax.TaxRate, 2);//税额
                                        decimal NoTaxMoney = Math.Round(Qty * TaxPrice / (1 + taxSch.TaxScheduleTaxs[0].Tax.TaxRate), 2);//未税金额
                                        accDetail.TaxPrice = decimal.Parse(apbillLine.Price);//含税单价
                                        accDetail.NoTaxPrice = NoTaxPrice;//未税单价
                                        accDetail.TaxMoney = TaxMoney;//税额
                                        accDetail.NoTaxMoney = NoTaxMoney;//未税金额
                                        accDetail.TotalMoney = Qty * TaxPrice;//总金额
                                    }
                                    else
                                    {
                                        decimal Qty = decimal.Parse(apbillLine.Qty);
                                        decimal TaxPrice = decimal.Parse(apbillLine.Price);
                                        decimal NoTaxPrice = Math.Round(TaxPrice, 2);
                                        decimal TaxMoney = 0;
                                        decimal NonTax = Math.Round(Qty * TaxPrice, 2);

                                        accDetail.TaxPrice = decimal.Parse(apbillLine.Price);//含税单价
                                        accDetail.NoTaxPrice = NoTaxPrice;//未税单价
                                        accDetail.TaxMoney = TaxMoney;//税额
                                        accDetail.NoTaxMoney = NonTax;//未税金额
                                        accDetail.TotalMoney = Qty * TaxPrice;//总金额
                                    }
                                }
                                apiDto.AccrueDetailDTOs.Add(accDetail);
                            }
                            int sup = 0;
                            UFIDA.U9.PM.Rcv.Receivement receivement = UFIDA.U9.PM.Rcv.Receivement.Finder.Find("DocNo='" + item.APbilLine[0].SrcDocNo + "'  and   Org=" + Context.LoginOrg.ID + "  ");
                            foreach (APbilLine apbillLine in item.APbilLine)
                            {
                                UFIDA.U9.PM.Rcv.RcvLine rcvline = UFIDA.U9.PM.Rcv.RcvLine.Finder.Find("Receivement.DocNo='" + apbillLine.SrcDocNo + "' and  DocLineNo = '" + apbillLine.SrcDocLineNo + "'  and  Receivement.Org=" + Context.LoginOrg.ID + "  ");
                                if (rcvline.Receivement.Supplier.Code != receivement.Supplier.Code)
                                {
                                    sup++;
                                }
                            }
                            if (sup > 0)
                            {
                                throw new Exception("来源单据的供应商必须一致!");
                            }
                            apiDto.CusOrSuppCode = receivement.Supplier.Code;
                            apiDto.CusOrSuppSiteCode = receivement.Supplier.Supplier.DefaultBillTo.Code;
                            apiDto.Currency = receivement.AC.ID;
                            apiDto.FIOrg = Context.LoginOrg.ID;
                            apiDto.SrcOrg = Context.LoginOrg.ID;
                            apiDto.IsMerge = true;//是否合并开票

                            proxy.AccrueAPIDTO = apiDto;
                            List<long> da = proxy.Do();

                            UFIDA.U9.AP.APBill.APBillHead head = UFIDA.U9.AP.APBill.APBillHead.Finder.FindByID(da[0].ToString());
                            using (ISession session = Session.Open())
                            {
                                head.DescFlexField.PrivateDescSeg1 = item.SrcSystemType;
                                head.InvoiceNum = item.InvoiceNum;
                                if (!string.IsNullOrEmpty(item.InvoiceDate))
                                {
                                    head.InvoiceDate = DateTime.Parse(item.InvoiceDate);
                                }

                                session.Commit();
                            }
                            #endregion 创建应付单

                            #region 调用接口，推送数据


                            bool bo = Publics.GetSRMXml("APBil", out string Url);
                            if (!bo)
                            {
                                throw new Exception("获取SRM接口地址失败，请检查配置文件!");
                            }
                            RequestParam requestParam = new RequestParam();
                            requestParam.bus_account = "3074078";
                            requestParam.interface_code = "JK20251022000002";
                            requestParam.body = new RequestBody();
                            RequestBody requestBody = new RequestBody();
                            RequestData requestData = new RequestData();
                            requestData.reconciliationNumber = item.SrcSystemType;
                            requestData.code = "200";
                            requestData.message = "创建应付单成功";
                            requestData.docNo = head.DocNo;
                            requestBody.data = requestData;
                            requestParam.body = requestBody;
                            string text = Publics.TransJsonByList(requestParam);
                            string msg = Publics.StartCalling(Url, text);
                            Publics.WriteLogFile("应付单新增推送SRM开始，请求参数:" + text);
                            if (!string.IsNullOrEmpty(msg))
                            {
                                throw new Exception("应付单同步SRM失败:" + msg);
                            }
                            resulet = "200";
                            #endregion 调用接口，推送数据

                            #region 更新状态删除遗留数据
                            PLCacheManager.DataCache.FlushCache();
                            PLCacheManager.ObjectCache.FlushCache();
                            using (UBFTransactionScope scopeUpdate = new UBFTransactionScope(TransactionOption.RequiresNew))
                            {
                                string sql = string.Format("update Cust_OTD_ZF_APbilHead set IsSuccess=1,OrderStatus=1 where ID='{0}'", item.ID);
                                DataAccessor.RunSQL(DataAccessor.GetConn(), sql.ToString(), null);
                                scopeUpdate.Commit();
                            }
                            #endregion 更新状态删除遗留数据
                            //成功
                            scope.Commit();

                        //清除对应Redis缓存
                        cache.Remove(item.SrcSystemType);
                        cache.Dispose();

                        }
                        catch (Exception e)
                        {
                           // 失败
                            scope.Rollback();

                            bool bo = Publics.GetSRMXml("APBil", out string Url);
                            if (!bo)
                            {
                                throw new Exception("获取SRM接口地址失败，请检查配置文件!");
                            }
                            RequestParam requestParam = new RequestParam();
                            requestParam.bus_account = "3074078";
                            requestParam.interface_code = "JK20251022000002";
                            requestParam.body = new RequestBody();
                            RequestBody requestBody = new RequestBody();
                            RequestData requestData = new RequestData();
                            requestData.reconciliationNumber = item.SrcSystemType;
                            requestData.code = "500";
                            requestData.message = "创建应付单失败 原因是" + e.Message;
                            requestData.docNo = "";
                            requestBody.data = requestData;
                            requestParam.body = requestBody;
                            string text = Publics.TransJsonByList(requestParam);
                            string msg = Publics.StartCalling(Url, text);
                            Publics.WriteLogFile("应付单创建失败推送SRM开始，请求参数:" + text);
                            if (!string.IsNullOrEmpty(msg))
                            {
                                Publics.WriteLogFile("应付单创建失败推送SRM失败，原因是:" + msg);
                            }
                            #region 更新状态删除遗留数据
                            PLCacheManager.DataCache.FlushCache();
                            PLCacheManager.ObjectCache.FlushCache();
                            #endregion 更新状态删除遗留数据
                            //using (ISession seesion = Session.Open())
                            //{
                            //    item.IsSuccess = false;
                            //    item.OrderStatus = APBilOrderStatusEnum.ErrorOrder;
                            //    seesion.Commit();
                            //    scope.Commit();
                            //}
                            //Reids缓存移除
                            cache.Remove(item.SrcSystemType);
                            using (UBFTransactionScope scopeUpdate = new UBFTransactionScope(TransactionOption.RequiresNew))
                            {
                                string sql = string.Format("update Cust_OTD_ZF_APbilHead set IsSuccess=0,OrderStatus=3,ErroMsg='{0}' where ID='{1}'", e.Message, item.ID);
                                DataAccessor.RunSQL(DataAccessor.GetConn(), sql.ToString(), null);
                                scopeUpdate.Commit();
                            }
                            throw new Exception(e.Message);
                        }
                    }

                }
                else
                {
                    throw new Exception(item.SrcSystemType+"该数据正在处理，请稍后操作");
                }

                //returnMsg.code = "200";
                //returnMsg.status = "1";
                //returnMsg.data = new Data();
                //returnMsg.data.DocNo = head.DocNo;
                //returnMsg.msg = "创建成功";
            }
            return resulet;
            #endregion 批量立应付SV
            
        }


        /// <summary>
        /// 最外层入参对象
        /// </summary>
        public class RequestParam
    {
        /// <summary>
        /// 业务账号
        /// </summary>
        [JsonProperty("bus_account")]  // System.Text.Json特性
                                           // [JsonProperty("bus_account")]   // 若用Newtonsoft.Json则启用此行
        public string bus_account { get; set; }

        /// <summary>
        /// 接口编码
        /// </summary>
        [JsonProperty("interface_code")]
        // [JsonProperty("interface_code")]
        public string interface_code { get; set; }

        /// <summary>
        /// 主体内容（嵌套对象）
        /// </summary>
        [JsonProperty("body")]
        // [JsonProperty("body")]
        public RequestBody body { get; set; }
    }

    /// <summary>
    /// 入参中的body对象
    /// </summary>
    public class RequestBody
    {
        /// <summary>
        /// 数据内容（嵌套对象）
        /// </summary>
        [JsonProperty("data")]
        // [JsonProperty("data")]
        public RequestData data { get; set; }
    }

    /// <summary>
    /// body中的data对象
    /// </summary>
    public class RequestData
    {
        /// <summary>
        /// 对账编号
        /// </summary>
        [JsonProperty("reconciliationNumber")]
        // [JsonProperty("reconciliationNumber")]
        public string reconciliationNumber { get; set; }

        /// <summary>
        /// 状态码
        /// </summary>
        [JsonProperty("code")]
        // [JsonProperty("code")]
        public string code { get; set; }  // 此处用string，因JSON中是字符串形式的"200"

        /// <summary>
        /// 消息内容
        /// </summary>
        [JsonProperty("message")]
        // [JsonProperty("message")]
        public string message { get; set; }

        /// <summary>
        /// 单据编号
        /// </summary>
        [JsonProperty("docNo")]
        // [JsonProperty("docNo")]
        public string docNo { get; set; }
    }
}

	#endregion
	
	
}